package com.yiren.backstage.communication.thread;

import android.content.Context;

import com.yiren.backstage.communication.api.AbstractCommunication;
import com.yiren.backstage.communication.api.impl.BluetoothCommunicationApiImpl;
import com.yiren.backstage.communication.api.impl.SerialCommunicationApiImpl;
import com.yiren.backstage.communication.interfaces.OnRTKDataListener;
import com.yiren.backstage.config.enums.RoverStationEnum;
import com.yiren.backstage.currency.constant.SignalGConstant;
import com.yiren.backstage.currency.utils.DateUtil;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;

/**
 * RTK差分数据透传
 * $JXST  RTK透传状态
 * $JXS   非RTK透传状态
 * $JX    非RTK透传状态, 可以接收AT指令
 */
public class RTKConnection {

    private static final String diffIp = "cs-dj-rover.dj23.cn";
    //    private static final String diffIp = "218.77.108.2";
    private static final int diffPort = 15002;

    private DifferenceThread differenceThread;
    private SetRtkModeThread setRtkModeThread;
    private int restartCount = 0;   //重连的次数

    private int differenceState = State_Difference_Idle;
    private String diffId = null;
    private static boolean isNonFourG = false;

    public final static int State_Device_Idle = 0;
    public final static int State_Device_Connecting = 1;
    public final static int State_Device_Connected = 2;
    public final static int State_Device_Disconnecting = 3;

    public final static int State_Difference_Idle = 4;
    public final static int State_Difference_Connecting = 5;
    public final static int State_Difference_Connected = 6;
    public final static int State_Difference_Disconnecting = 7;

    public final static int State_Difference_Code = 8;  // 指令模式
    public final static int State_difference_Trans = 9; // 透传模式

    private boolean isCommand = false;       //是否是指令模式
    public static boolean useCommand = false;//是否使用指令模式
    private boolean isFinish = true;         //判断主页面是否关闭
    private RoverStationEnum curStationMode; //是否是4G模式

    private static Context mContext;
    private OnRTKDataListener onRTKDataListener;
    private final static RTKConnection single = new RTKConnection();

    private OnConnectionListener listener;
    private long lastReadTime = System.currentTimeMillis();

    private long exceptionTime = System.currentTimeMillis();

    public static RTKConnection getInstance(Context context) {
        mContext = context;
        return single;
    }

    public static RTKConnection getInstance() {
        return single;
    }

    public RTKConnection() {
    }

    public void setOnConnectionListener(OnConnectionListener listener) {
        this.listener = listener;
    }

    public void setDifferenceState(int differenceState) {
        this.differenceState = differenceState;
    }

    public int getDifferenceState() {
        return differenceState;
    }

    public void setDiffId(String diffId) {
        this.diffId = diffId;
    }

    public String getDiffId() {
        return diffId;
    }

    public static void setIsNonFourG(boolean isNonFourGVal) {
        isNonFourG = isNonFourGVal;
    }

    public static boolean getIsNonFourG() {
        return isNonFourG;
    }

    public void setOnRTKDataListener(OnRTKDataListener onRTKDataListener) {
        this.onRTKDataListener = onRTKDataListener;
    }

    public void setCurStationMode(RoverStationEnum curStationMode) {
        this.curStationMode = curStationMode;
    }

    public void start() {
        restartCount++;
        isFinish = false;
        if (setRtkModeThread == null) {
            useCommand = false;
            setRtkModeThread = new SetRtkModeThread();
            setRtkModeThread.setDaemon(true);
            setRtkModeThread.start();
        }
        differenceState = State_Difference_Idle;
        if (restartCount > 2) {
            //测试时候发现，切换网络的时候会出现differenceThread不为空，但是differenceThread没启动的情况，当重新连接次数大于2次还没有连接上，则重新new一个
            if (differenceThread != null) {
                differenceThread.close();
                differenceThread = new DifferenceThread();
                differenceThread.start();
                restartCount = 0;
                addBasket("_restart()");
            }
        } else {
            if (differenceThread == null) {
                differenceThread = new DifferenceThread();
                differenceThread.start();
                addBasket("_start()");
            }
        }
    }

    public void stop() {
        useCommand = true;
        isFinish = true;
        if (setRtkModeThread != null) {
            setRtkModeThread.interrupt();
        }
        differenceState = State_Difference_Disconnecting;
        diffId = null;
        if (differenceThread != null) {
            differenceThread.close();
            differenceThread.interrupt();
        }
    }

    private class SetRtkModeThread extends Thread {

        @Override
        public void run() {
            while (!isFinish) {
                try {
                    if (SignalGConstant.MODE_COMMAND) {
                        isCommand = true;
                        if (!useCommand) {
                            //如果不使用指令模式，则切换为透传模式
                            addBasket("_" + Thread.currentThread().getId() + "_AT+RTKTS\r\n");
                            SerialCommunicationApiImpl.getInstance(mContext).writeData("AT+RTKTS\r\n".getBytes(), "", null);
                        }
                        Thread.sleep(500);
                    } else {
                        isCommand = false;
                    }
                    if (System.currentTimeMillis() - lastReadTime > 15 * 1000 && !isFinish) {
                        lastReadTime = System.currentTimeMillis();
                        RTKConnection.getInstance(mContext).start();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private class DifferenceThread extends Thread {

        private Socket socket;
        private InputStream is;
        private OutputStream os;
        private byte[] data;

        @Override
        public void run() {
            while (differenceState == State_Difference_Idle && diffId != null && diffIp != null && diffPort > 1024 && !isFinish) {
                try {
                    differenceState = State_Difference_Connecting;
                    //if (listener != null) listener.onDifferenceStateChange(differenceState, "差分网络正在连接...");
                    socket = new Socket();
                    socket.connect(new InetSocketAddress(diffIp, diffPort), 3000);
//                    socket.setKeepAlive(true);
                    is = socket.getInputStream();
                    os = socket.getOutputStream();
                    differenceState = State_Difference_Connected;
                    Thread.sleep(500);
                    int nonDataCount = 0;
                    int heart = 0;
                    data = new byte[1024];
                    os.write(diffId.getBytes());
                    while (differenceState == State_Difference_Connected && !isFinish) {
                        int size = is.read(data);
                        restartCount = 0;
                        lastReadTime = System.currentTimeMillis();
                        if (size > 0) {
                            if (size != 5) {
                                exceptionTime = System.currentTimeMillis();
                            }
                            nonDataCount = 0;
                            heart++;
                            if (size < data.length && !isCommand && !useCommand) {
                                addBasket("_" + Thread.currentThread().getId() + "_size=" + size);
                                if (curStationMode != RoverStationEnum.HAS_CARD_ROVER_STATION) {
                                    if (SignalGConstant.isOpen){
                                        BluetoothCommunicationApiImpl.getInstance(mContext).writeData(data, "", null);
                                    }else {
                                        SerialCommunicationApiImpl.getInstance(mContext).writeData(data, "", null);
                                    }
                                }
                            }
                        } else {
                            nonDataCount++;
                            os.write("12356".getBytes());
                        }
                        if (heart >= 10) {
                            addBasket("_12356");
                            os.write("12356".getBytes());
                            heart = 0;
                            //if (listener != null) listener.onDifferenceStateChange(differenceState, "发送心跳包!" + SignalG.carMasterDataJX + "---" + size);
                        }
                        if (nonDataCount >= 30) {
                            close();
                            nonDataCount = 0;
                        }
                        Thread.sleep(200);
                    }
                } catch (Exception e) {
                    long curTime = System.currentTimeMillis();
                    long abs = Math.abs(curTime - exceptionTime);
                    if (abs >= 30 * 1000 && listener != null) {
                        listener.onDifferenceStateChange(differenceState, "差分网络连接异常!");
                    }
                    addBasket("_差分网络连接异常_" + e.getMessage());
                    differenceState = State_Difference_Idle;
                    restartCount = 0;
                    e.printStackTrace();
                }
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    differenceState = State_Difference_Idle;
                    e.printStackTrace();
                }
            }
        }

        void close() {
            differenceState = State_Difference_Disconnecting;
            try {
                if (is != null) {
                    is.close();
                    is = null;
                }
                if (os != null) {
                    os.close();
                    os = null;
                }
                if (socket != null) {
                    socket.close();
                    socket = null;
                }
                addBasket("_close()");
            } catch (Exception e) {
                e.printStackTrace();
            }
            differenceState = State_Difference_Idle;
        }
    }

    public void addBasket(String s) {
        if (null != onRTKDataListener) {
            onRTKDataListener.onRTKData(DateUtil.getCurrentDate() + s);
        }
    }

    public interface OnConnectionListener {
        void onDifferenceStateChange(int state, String message);
    }


}
